package com.ruoyi.pay.refund.wx.service;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.config.mapper.ApplicationConfigMapper;
import com.ruoyi.config.mapper.WxpayConfigMapper;
import com.ruoyi.pay.refund.wx.vo.TransferCancelResponse;
import com.ruoyi.pay.refund.wx.vo.TransferCreateRequest;
import com.ruoyi.pay.refund.wx.vo.TransferCreateResponse;
import com.ruoyi.pay.refund.wx.vo.TransferQueryResponse;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.cipher.PrivacyDecryptor;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.http.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

@Slf4j
@Service
public class TransferNewService {

    @Resource
    private ApplicationConfigMapper applicationConfigMapper;
    @Resource
    private WxpayConfigMapper wxpayConfigMapper;

    // 使用 AtomicReference 确保线程安全，并且可以延迟初始化
    private final AtomicReference<Config> configRef = new AtomicReference<>();
    private final AtomicReference<HttpClient> httpClientRef = new AtomicReference<>();
    private final AtomicReference<PrivacyEncryptor> encryptorRef = new AtomicReference<>();
    private final AtomicReference<PrivacyDecryptor> decryptorRef = new AtomicReference<>();

    // 懒加载 Config 对象
    public Config getConfig() {
        return getLazyLoadedInstance(configRef, this::initializeConfig);
    }

    // 懒加载 HttpClient 对象
    public HttpClient getHttpClient() {
        return getLazyLoadedInstance(httpClientRef, this::initializeHttpClient);
    }

    // 懒加载 PrivacyEncryptor 对象
    public PrivacyEncryptor getEncryptor() {
        return getLazyLoadedInstance(encryptorRef, this::initializeEncryptor);
    }

    // 懒加载 PrivacyDecryptor 对象
    public PrivacyDecryptor getDecryptor() {
        return getLazyLoadedInstance(decryptorRef, this::initializeDecryptor);
    }

    // 通用的懒加载方法，使用双重检查锁定模式
    private <T> T getLazyLoadedInstance(AtomicReference<T> ref, Supplier<T> supplier) {
        T instance = ref.get();
        if (instance == null) {
            synchronized (this) {
                instance = ref.get();
                if (instance == null) {
                    instance = supplier.get();
                    ref.set(instance);
                }
            }
        }
        return instance;
    }

    // 初始化 Config 对象的方法
    private Config initializeConfig() {
        String mchId = wxpayConfigMapper.selectOneData("mchId");
        String mchSerialNo = wxpayConfigMapper.selectOneData("mchSerialNo");
        String privateKeyPath = wxpayConfigMapper.selectOneData("privateKeyPath");
        String apiV3Key = wxpayConfigMapper.selectOneData("apiV3Key");
        return new RSAAutoCertificateConfig.Builder()
                .merchantId(mchId)
                .privateKey(getPrivateKey(privateKeyPath))
                .merchantSerialNumber(mchSerialNo)
                .apiV3Key(apiV3Key)
                .build();
    }

    // 初始化 HttpClient 对象的方法
    private HttpClient initializeHttpClient() {
        Config config = getConfig(); // 确保 Config 已初始化
        return new DefaultHttpClientBuilder()
                .credential(Objects.requireNonNull(config.createCredential()))
                .validator(Objects.requireNonNull(config.createValidator()))
                .build();
    }

    // 初始化 PrivacyEncryptor 对象的方法
    private PrivacyEncryptor initializeEncryptor() {
        Config config = getConfig(); // 确保 Config 已初始化
        return config.createEncryptor();
    }

    // 初始化 PrivacyDecryptor 对象的方法
    private PrivacyDecryptor initializeDecryptor() {
        Config config = getConfig(); // 确保 Config 已初始化
        return config.createDecryptor();
    }


    //public Map<String, Object> getConfig() {
    //    String mchId = wxpayConfigMapper.selectOneData("mchId");
    //    String mchSerialNo = wxpayConfigMapper.selectOneData("mchSerialNo");
    //    String privateKeyPath = wxpayConfigMapper.selectOneData("privateKeyPath");
    //    String apiV3Key = wxpayConfigMapper.selectOneData("apiV3Key");
    //
    //    Config config = (Config) map.get("config");
    //    if (CheckEmptyUtil.isEmpty(config)) {
    //        // 可以根据实际情况使用publicKeyFromPath或publicKey加载公钥
    //        config = new RSAAutoCertificateConfig.Builder()
    //                .merchantId(mchId)
    //                .privateKey(getPrivateKey(privateKeyPath))
    //                .merchantSerialNumber(mchSerialNo)
    //                .apiV3Key(apiV3Key)
    //                .build();
    //        map.put("config", config);
    //    }
    //    HttpClient httpClient = (HttpClient) map.get("httpClient");
    //    if (CheckEmptyUtil.isEmpty(httpClient)) {
    //        httpClient =
    //                new DefaultHttpClientBuilder()
    //                        .credential(Objects.requireNonNull(config.createCredential()))
    //                        .validator(Objects.requireNonNull(config.createValidator()))
    //                        .build();
    //        map.put("httpClient", httpClient);
    //    }
    //    PrivacyEncryptor encryptor = (PrivacyEncryptor) map.get("encryptor");
    //    if (CheckEmptyUtil.isEmpty(httpClient)) {
    //        encryptor = config.createEncryptor();
    //        map.put("encryptor", encryptor);
    //    }
    //    PrivacyDecryptor decryptor = (PrivacyDecryptor) map.get("decryptor");
    //    if (CheckEmptyUtil.isEmpty(httpClient)) {
    //        decryptor = config.createDecryptor();
    //        map.put("decryptor", decryptor);
    //    }
    //    return map;
    //}

    public PrivateKey getPrivateKey(String url) {
        log.info("weChatPayPrivateKeyUrl:{}", url);

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(url);
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                String content = EntityUtils.toString(response.getEntity(), "utf-8");
                String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                        .replace("-----END PRIVATE KEY-----", "")
                        .replaceAll("\\s+", "");
                KeyFactory kf = KeyFactory.getInstance("RSA");
                PrivateKey key = kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
                return key;
            }
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info("获取私钥已完成");
        return null;
    }

    /**
     * 创建商家转账订单
     *
     * @param request 请求参数
     * @return 响应参数
     */
    public TransferCreateResponse createTransferOrder(TransferCreateRequest request, String env, Integer type) {
        PrivacyEncryptor encryptor = getEncryptor();
        String appid;
        if (env.equals("H5")) {
            appid = applicationConfigMapper.selectData("account_appid");
        } else {
            if (type == 1) {
                //用户
                appid = applicationConfigMapper.selectData("app_appid");
            } else {
                //技师
                appid = applicationConfigMapper.selectData("technician_app_appid");
            }

        }
        String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";
        Objects.requireNonNull(encryptor);
        request.setAppid(appid);
        return executeHttpRequest(requestPath, HttpMethod.POST, request.toString(), TransferCreateResponse.class);
    }

    /**
     * 撤销商家转账订单
     * 商户通过转账接口发起付款后，在用户确认收款之前可以通过该接口撤销付款。
     * 该接口返回成功仅表示撤销请求已受理，
     * 系统会异步处理退款等操作，
     * 以最终查询单据返回状态为准。
     *
     * @param outBillNo 商户转账单号
     * @return 响应参数
     */
    public TransferCancelResponse cancelTransferOrder(String outBillNo) {

        String requestPath =
                "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}/cancel";
        requestPath =
                requestPath.replace("{" + "out_bill_no" + "}", outBillNo);
        return executeHttpRequest(requestPath, HttpMethod.POST, null, TransferCancelResponse.class);
    }

    public TransferQueryResponse queryTransferByOutBillNo(String outBillNo) {
        PrivacyDecryptor decryptor = getDecryptor();
        String requestPath =
                "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}";
        requestPath =
                requestPath.replace("{" + "out_bill_no" + "}", outBillNo);
        TransferQueryResponse response = executeHttpRequest(requestPath, HttpMethod.GET, null, TransferQueryResponse.class);
        response.setUserName(decryptor.decrypt(response.getUserName()));
        return response;
    }

    public TransferQueryResponse queryTransferByTransferBillNo(String transferBillNo) {
        PrivacyDecryptor decryptor = getDecryptor();
        String requestPath =
                "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/transfer-bill-no/{transfer_bill_no}";
        requestPath =
                requestPath.replace("{" + "transfer_bill_no" + "}", transferBillNo);
        TransferQueryResponse response = executeHttpRequest(requestPath, HttpMethod.GET, null, TransferQueryResponse.class);
        response.setUserName(decryptor.decrypt(response.getUserName()));
        return response;
    }

    public <T> T executeHttpRequest(String requestPath, HttpMethod method, String body, Class<T> responseClass) {
        HttpClient httpClient = getHttpClient();
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
        headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
        HttpRequest httpRequest =
                new HttpRequest.Builder()
                        .httpMethod(method)
                        .url(requestPath)
                        .headers(headers)
                        .body(StringUtils.hasText(body) ? new JsonRequestBody.Builder().body(body).build() : null)
                        .build();
        HttpResponse<T> httpResponse =
                httpClient.execute(httpRequest, responseClass);
        return httpResponse.getServiceResponse();
    }
}